package com.yay.rental.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import java.io.FileNotFoundException;
import java.util.Arrays;

import com.yay.rental.provider.RentalContract.Category;
import com.yay.rental.provider.RentalContract.Rental;
import com.yay.rental.provider.RentalContract.RentalMap;
import com.yay.rental.provider.RentalDatabase.Tables;
import com.yay.rental.util.SelectionBuilder;


/**
 * Get Started!
 * @author team@getstarted.com.ua
 * 
 * Provider that stores {@link RentalContract} data. 
 */
public class RentalProvider extends ContentProvider {
    private static final String TAG = "RentalProvider";
    private static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);

    private RentalDatabase mOpenHelper;

    private static final UriMatcher sUriMatcher = buildUriMatcher();

    private static final int CATEGORY = 200;
    private static final int CATEGORY_RENTAL = 201;

    private static final int RENTAL = 300;
    private static final int RENTAL_ID = 301;
    
    private static final int MAP = 400;
    
    /**
     * Build and return a {@link UriMatcher} that catches all {@link Uri}
     * variations supported by this {@link ContentProvider}.
     */
    private static UriMatcher buildUriMatcher() {
        final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
        final String authority = RentalContract.CONTENT_AUTHORITY;

        matcher.addURI(authority, "category/*", CATEGORY);
        matcher.addURI(authority, "category/*/rental", CATEGORY_RENTAL);

        matcher.addURI(authority, "rental", RENTAL);
        matcher.addURI(authority, "rental/*", RENTAL_ID);

        matcher.addURI(authority, "map", MAP);
        
        return matcher;
    }

    @Override
    public boolean onCreate() {
        final Context context = getContext();
        mOpenHelper = new RentalDatabase(context);
        return true;
    }

    /** {@inheritDoc} */
    @Override
    public String getType(Uri uri) {
        final int match = sUriMatcher.match(uri);
        switch (match) {
            case CATEGORY:
                return Category.CONTENT_TYPE;
            case CATEGORY_RENTAL:
                return Rental.CONTENT_TYPE;    
            case RENTAL:
                return Rental.CONTENT_TYPE;
            case RENTAL_ID:
                return Rental.CONTENT_ITEM_TYPE;
            case MAP:
                return RentalMap.CONTENT_TYPE;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
    }

    /** {@inheritDoc} */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        if (LOGV) Log.v(TAG, "query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")");
        final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        final int match = sUriMatcher.match(uri);
        switch (match) {
            default: {
                // Most cases are handled with simple SelectionBuilder
                final SelectionBuilder builder = buildExpandedSelection(uri, match);
                return builder.where(selection, selectionArgs).query(db, projection, sortOrder);
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        if (LOGV) Log.v(TAG, "insert(uri=" + uri + ", values=" + values.toString() + ")");
        final int match = sUriMatcher.match(uri);
        switch (match) {
            default: {
                throw new UnsupportedOperationException("Unknown uri: " + uri);
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        Log.d(TAG, "update(uri=" + uri + ", values=" + values.toString() + ")");
        final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        final SelectionBuilder builder = buildSimpleSelection(uri);
        return builder.where(selection, selectionArgs).update(db, values);
    }

    /** {@inheritDoc} */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        if (LOGV) Log.v(TAG, "delete(uri=" + uri + ")");
        final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        final SelectionBuilder builder = buildSimpleSelection(uri);
        return builder.where(selection, selectionArgs).delete(db);
    }

    /**
     * Build a simple {@link SelectionBuilder} to match the requested
     * {@link Uri}. This is usually enough to support {@link #insert},
     * {@link #update}, and {@link #delete} operations.
     */
    private SelectionBuilder buildSimpleSelection(Uri uri) {
        final SelectionBuilder builder = new SelectionBuilder();
        final int match = sUriMatcher.match(uri);
        switch (match) {
            case CATEGORY: {
                final String categoryId = Category.getCategoryId(uri);
                if("0".equals(categoryId)) {
                    return builder.table(Tables.CATEGORIES);
                } else {
                    return builder.table(Tables.CATEGORIES).where(Category.IDP + "=?", categoryId);
                }
            }
            case CATEGORY_RENTAL: {
            	//final String categoryId = Category.getCategoryId(uri);
                return builder.table(Tables.RENTALS);//.where(Rental.IDP + "=?", categoryId);
            }
            case RENTAL: {
                return builder.table(Tables.RENTALS);
            }
            case RENTAL_ID: {
            	final String rentalId = Rental.getRentalId(uri);
                return builder.table(Tables.RENTALS)
                        .where(Rental._ID + "=?", rentalId);
            }
            default: {
                throw new UnsupportedOperationException("Unknown uri: " + uri);
            }
        }
    }

    /**
     * Build an advanced {@link SelectionBuilder} to match the requested
     * {@link Uri}. This is usually only used by {@link #query}, since it
     * performs table joins useful for {@link Cursor} data.
     */
    private SelectionBuilder buildExpandedSelection(Uri uri, int match) {
        final SelectionBuilder builder = new SelectionBuilder();
        switch (match) {
	        case CATEGORY: {
                final String categoryId = Category.getCategoryId(uri);
                if("0".equals(categoryId)) {
                    return builder.table(Tables.CATEGORIES);
                } else {
                    return builder.table(Tables.CATEGORIES).where(Category.IDP + "=?", categoryId);
                }
	        }
            case CATEGORY_RENTAL: {
            	//final String categoryId = Category.getCategoryId(uri);
                return builder.table(Tables.RENTALS);//.where(Rental.IDP + "=?", categoryId);
            }
            case RENTAL: {
                return builder.table(Tables.RENTALS);
            }
            case RENTAL_ID: {
            	final String rentalId = Rental.getRentalId(uri);
                return builder.table(Tables.RENTALS).where(Rental._ID + "=?", rentalId);
            }
            default: {
                throw new UnsupportedOperationException("Unknown uri: " + uri);
            }
        }
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        final int match = sUriMatcher.match(uri);
        switch (match) {
            default: {
                throw new UnsupportedOperationException("Unknown uri: " + uri);
            }
        }
    }

}
